	
	private static final int SCREEN_SIZE = 600;
	private static final int ELLIPSE_SIZE = 20;
	private static final int OFFSET = 50;
	private static final int ELLIPSE_SPACING = 30;
	private static final int ELLIPSE_ROW_LENGTH = 16;
	
	private static final int MAX = 600;
	private static final int MIN = 0;
	
	private static final int SATURATION = 150;
	private static final int BRIGHTNESS = 150;
	
	private static final int HUE_MAX = 180;
	
	private int[][] data = new int[ELLIPSE_ROW_LENGTH][ELLIPSE_ROW_LENGTH];
	
	public void setup() {
		size(SCREEN_SIZE, SCREEN_SIZE);
		
		data[3][4] = MAX;
		data[7][9] = 565;
		data[10][15] = 40;
		data[9][13] = 120;
		data[15][0] = 550;

		colorMode(HSB);
	}
	
	public void draw() {
		background(200);
		
		int[][] weights = new int[ELLIPSE_ROW_LENGTH][ELLIPSE_ROW_LENGTH];
		for (int row = 0; row < ELLIPSE_ROW_LENGTH; row++) {
			for (int col = 0; col < ELLIPSE_ROW_LENGTH; col++) {
				if (data[row][col] > 0) {
					addWeight(weights, row, col, data[row][col]);
				}
			}
		}
		
		for (int i = 0; i < weights.length; i++) {
			for (int j = 0; j < weights[0].length; j++) {
				weights[i][j] = (int)map(weights[i][j], MIN, MAX, 0, HUE_MAX);
			}
		}
		
		ellipseMode(CENTER);
		
		for (int row = 0; row < ELLIPSE_ROW_LENGTH; row++) {
			for (int col = 0; col < ELLIPSE_ROW_LENGTH; col++) {
				fill(HUE_MAX - weights[row][col], SATURATION, BRIGHTNESS);
				ellipse(OFFSET + col * ELLIPSE_SPACING, OFFSET + row * ELLIPSE_SPACING, ELLIPSE_SIZE, ELLIPSE_SIZE);
			}
		}
	}

	private void addWeight(int[][] weights, int dataRow, int dataCol, int dataVal) {
		for (int weightRow = 0; weightRow < weights.length; weightRow++) {
			for (int weightCol = 0; weightCol < weights[0].length; weightCol++) {
				float distance = dist(weightRow, weightCol, dataRow, dataCol); 
				weights[weightRow][weightCol] += (1 / (distance + 1)) * dataVal;
			}
		}
	}
